package cn.xuan.scan.dao.impl;

import java.util.List;
import java.util.Vector;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate4.HibernateCallback;
import org.springframework.orm.hibernate4.SessionFactoryUtils;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;
import org.springframework.stereotype.Component;

import cn.xuan.scan.dao.CommonQueryDAO;
import cn.xuan.scan.dao.query.param.BundingChildren;
import cn.xuan.scan.dao.query.param.CommonQueryParam;
import cn.xuan.scan.dao.query.param.QueryTree;

@Component
public class CommonQueryDAOImpl extends HibernateDaoSupport implements CommonQueryDAO{ 
	
	@Resource(name = "sessionFactory")
	private void setMySessionFactory(SessionFactory sessionFactory) {
		// 这个方法名可以随便写，@Resource可以通过name 或者type来装载的。
		super.setSessionFactory(sessionFactory);
	}
	
    public Object findObjectByHql(String hql)throws Exception{
        List list = this.findObjectsByHql(hql);
        if ((null != list) && (list.size() > 0)) {
            return list.get(0);
        }
        return null;
    }
    
    public List findObjectsByHql(String hql)throws Exception{
        Session session =null;
        try
        {
            session = this.getSessionFactory().openSession(); // this.getSessionFactory().getCurrentSession(); // this.getSession(false);
            //System.out.println("session: " + session.hashCode());
            //System.out.println("getSession(): " + this.hashCode());
            List result = null;
            Query query = session.createQuery(hql);  
            result = query.list();
            return result;
        }
        catch(Exception e)
        {
            throw e;
        }
        finally
        {
            //System.out.println("releaseSession(): " + session.hashCode());
        	SessionFactoryUtils.closeSession(session);
        }
        //return getHibernateTemplate().find(hql);
    }
    
    public List findObjectsPagedByHql(String hql,Integer begin,Integer end) throws Exception{
        Session session =null;
        try
        {
            session = this.getSessionFactory().openSession(); //  this.getSession(false);
            //System.out.println("session: " + session.hashCode());
            //System.out.println("getSession(): " + this.hashCode());
            Query query = session.createQuery(hql);  
            query.setFirstResult(begin.intValue()); 
            query.setMaxResults(end.intValue()-begin.intValue());
            List list = query.list();
            System.out.println("hql: "+hql);
            System.out.println("param: begin-"+begin+" end-"+end+" query result: "+list.size());
            return list;
        }
        catch(Exception e)
        {
            throw e;
        }
        finally
        {
            //System.out.println("releaseSession(): " + session.hashCode());
        	SessionFactoryUtils.closeSession(session);// this.releaseSession(session);
        }
    }
    
    public List queryObjects(CommonQueryParam commonQueryParam) throws Exception
    {
        Session session =null;
        try
        {
            session = this.getSessionFactory().openSession(); // this.getSession(false);
            QueryTree queryTree = null;
            //System.out.println("session: " + session.hashCode());
            //System.out.println("getSession(): " + this.hashCode());
            List result = null;
            boolean hasChild = false;
            Vector vChildFetch = commonQueryParam.getChildrenFetchs();
            if (vChildFetch!=null && vChildFetch.size()>0)
            {
                //有拼装字符串
                hasChild = true;
                queryTree = new QueryTree(commonQueryParam.getEntityClass());
                for (int i=0; i<vChildFetch.size(); i++)
                {
                    queryTree.addQueryPath((String)vChildFetch.get(i));
                }
            }
            if (commonQueryParam.getQueryHql() != null) 
            {
                //hql查询的情况
                if(commonQueryParam.getBegin()!=null && commonQueryParam.getEnd()!=null)
                {
                    Query query = session.createQuery(commonQueryParam.getQueryHql());  
                    query.setFirstResult(commonQueryParam.getBegin().intValue()); 
                    query.setMaxResults(commonQueryParam.getEnd().intValue()-commonQueryParam.getBegin().intValue());
                    result = query.list();
                }
                else
                {
                    Query query = session.createQuery(commonQueryParam.getQueryHql());  
                    result = query.list();
                }
            } 
            else
            {
                Criteria criteria = session.createCriteria(commonQueryParam.getEntityClass());
                //条件
                Vector vExpression = commonQueryParam.getExpressions();
                for (int i=0; i<vExpression.size(); i++)
                {
                    criteria.add((Criterion)vExpression.get(i));
                }
                
                //分组
                if(commonQueryParam.getBegin()!=null && commonQueryParam.getEnd()!=null)
                {
                    criteria.setFirstResult(commonQueryParam.getBegin().intValue());
                    criteria.setMaxResults(commonQueryParam.getEnd().intValue()-commonQueryParam.getBegin().intValue());
                }
                
                //降序
                Vector vDesc = commonQueryParam.getOrderByDescs();
                for (int i=0; i<vDesc.size(); i++)
                {
                    String descField = (String)vDesc.get(i);
                    criteria.addOrder(Order.desc(descField));
                }
                //升序
                Vector vAsc = commonQueryParam.getOrderByAscs();
                for (int i=0; i<vAsc.size(); i++)
                {
                    String ascField = (String)vAsc.get(i);
                    criteria.addOrder(Order.asc(ascField));
                }
                //操作
                result = criteria.list();  
            }
            if (hasChild==true && result!=null && queryTree!=null)
            {
                for(int i=0; i<result.size(); i++)
                {
                    new BundingChildren(queryTree, result.get(i), session).getChildrenInst();
                }
            }
            return result;
        }
        catch(Exception e)
        {
            throw e;
        }
        finally
        {
            //System.out.println("releaseSession(): " + session.hashCode());
        	SessionFactoryUtils.closeSession(session);// this.releaseSession(session);
        }
    }
 
    public int queryObjectCount(CommonQueryParam commonQueryParam) throws Exception
    {
        Session session =null;
        try
        {
            session = this.getSessionFactory().openSession(); //this.getSession(false);
            int count=0;
            if(StringUtils.isNotEmpty(commonQueryParam.getQueryHql())){
            	count=session.createQuery(commonQueryParam.getQueryHql()).list().size();
            }else{
                //System.out.println("session: " + session.hashCode());
                //System.out.println("getSession(): " + this.hashCode());
                Criteria criteria = session.createCriteria(commonQueryParam.getEntityClass());
                //条件
                Vector vExpression = commonQueryParam.getExpressions();
                for (int i=0; i<vExpression.size(); i++)
                {
                    criteria.add((Criterion)vExpression.get(i));
                }
                
                //分组
                if(commonQueryParam.getBegin()!=null && commonQueryParam.getEnd()!=null)
                {
                    //criteria.setFirstResult(commonQueryParam.getBegin().intValue());
                    criteria.setFirstResult(0);
                    criteria.setMaxResults(commonQueryParam.getEnd().intValue()-commonQueryParam.getBegin().intValue());
                }
                
                //降序
                Vector vDesc = commonQueryParam.getOrderByDescs();
                for (int i=0; i<vDesc.size(); i++)
                {
                    String descField = (String)vDesc.get(i);
                    criteria.addOrder(Order.desc(descField));
                }
                //升序
                Vector vAsc = commonQueryParam.getOrderByAscs();
                for (int i=0; i<vAsc.size(); i++)
                {
                    String ascField = (String)vAsc.get(i);
                    criteria.addOrder(Order.asc(ascField));
                }
                //操作
                count = getCountByCriteria(criteria); 

            }
 
            return count;
        }
        catch(Exception e)
        {
            throw e;
        }
        finally
        {
            //System.out.println("releaseSession(): " + session.hashCode());
        	SessionFactoryUtils.closeSession(session);// this.releaseSession(session);
        }
    }
    
    private int getCountByCriteria(final Criteria criteria) {
        Object count = getHibernateTemplate().execute(
            new HibernateCallback() 
            {
                public Object doInHibernate(Session session) throws HibernateException {
                    return criteria.setProjection(Projections.rowCount()).uniqueResult();
                }
            });
        return Integer.parseInt(count.toString());
    }

	@Override
	public Object queryObject(CommonQueryParam commonQueryParam) throws Exception {
		
		List list = this.queryObjects(commonQueryParam);
		
		return list != null && list.size() > 0 ? list.get(0) : null;
	}
    
}
